#include "BaseAI.h"
#include "AIManager.h"
#include "TileManager.h"
#include "BaseCharacter.h"
//#include "BaseInterface.h"
#include "Messages\CreateCharacterMessage.h"
#include "GamePlayState.h"

BaseAI::BaseAI(void)
{
	this->characterIndex = -1;
}


BaseAI::~BaseAI(void)
{
}

bool BaseAI::AIMove()
{
	BaseCharacter * bc = (*AIManager::GetInstance()->GetAIChars())[this->characterIndex];
	if(bc->GetHP() <=0)
		return false;
	TileManager * tm = TileManager::GetInstance();

	vector<Tile*> inRangeTiles;
	vector<BaseCharacter *> inRangeAllies;
	vector<BaseCharacter *> inRangeEnemies;

	for(int x = 0; x < TileManager::GetInstance()->GetSizeX();x++)
	{
		for(int y = 0; y < TileManager::GetInstance()->GetSizeY();y++)
		{
			Tile * tile = tm->GetTile(x,y);

			if(tile->GetCharacter() == nullptr)
				continue;

			int xRange = tile->GetX() - bc->GetTile()->GetX();
			int yRange = tile->GetY() - bc->GetTile()->GetY();

			if(xRange < 0)
				xRange = -xRange;

			if(yRange < 0)
				yRange = -yRange;

			if(!(xRange + yRange > bc->GetRng()))
			{
				if(tile->GetCharacter()->IsPlayer() == bc->IsPlayer())
					inRangeAllies.push_back(tile->GetCharacter());
				else
				{
					inRangeEnemies.push_back(tile->GetCharacter());
				}
			}


		}
	}

	for(int x = 0; x < TileManager::GetInstance()->GetSizeX();x++)
	{
		for(int y = 0; y < TileManager::GetInstance()->GetSizeY();y++)
		{
			Tile * tile = tm->GetTile(x,y);

			if(tile->GetCharacter() != nullptr || tile->GetObstacle())
				continue;

			int xRange = tile->GetX() - bc->GetTile()->GetX();
			int yRange = tile->GetY() - bc->GetTile()->GetY();

			if(xRange < 0)
				xRange = -xRange;

			if(yRange < 0)
				yRange = -yRange;

			if(!(xRange + yRange > bc->GetMov()))
			{
				if(tile->GetTerrainType() == GRASS || tile->GetTerrainType() == DIRT ||tile->GetTerrainType() == STONE_FLOOR ||tile->GetTerrainType() == WATER ||tile->GetTerrainType() == MUD||tile->GetTerrainType() == SNOW ||tile->GetTerrainType() == SHRUB)
				{
					inRangeTiles.push_back(tile);
				}
			}

		}
	}

	if(bc->GetHP() > bc->GetMaxHP()/4)
	{
		if(inRangeEnemies.size() > 0)
			return false;
		else
		{
			GamePlayState * g = GamePlayState::GetInstance();
			vector<BaseCharacter*> * chs = g->GetCharacters();
			
			BaseCharacter * closest = nullptr;

			for(unsigned int i = 0; i < chs->size();i++)
			{
				if(closest == nullptr)
				{
					if((*chs)[i]->IsPlayer() != bc->IsPlayer())
						closest = (*chs)[i];
				}
				else
				{
					int xRange = (*chs)[i]->GetTile()->GetX() - bc->GetTile()->GetX();
					int yRange = (*chs)[i]->GetTile()->GetY() - bc->GetTile()->GetY();

					if(xRange < 0)
						xRange = -xRange;

					if(yRange < 0)
						yRange = -yRange;

					int xRange2 = closest->GetTile()->GetX() - bc->GetTile()->GetX();
					int yRange2 = closest->GetTile()->GetY() - bc->GetTile()->GetY();

					if(xRange2 < 0)
						xRange2 = -xRange2;

					if(yRange2 < 0)
						yRange2 = -yRange2;

					if(xRange2+yRange2 > xRange+yRange)
					{
						if((*chs)[i]->IsPlayer() != bc->IsPlayer())
							closest = (*chs)[i];
					}

				}
			}

			bool moving = true;
			//vector<int> tried;

			while(moving && inRangeTiles.size() > 0)
			{
				Tile * closestToTarget = nullptr;
				int index;

				for(unsigned int i = 0; i < inRangeTiles.size();i++)
				{
					if(closestToTarget == nullptr)
					{
						closestToTarget = inRangeTiles[i];
						index = i;
					}
					else
					{
						int xRange = inRangeTiles[i]->GetX() - closest->GetTile()->GetX();
						int yRange = inRangeTiles[i]->GetY() - closest->GetTile()->GetY();

						if(xRange < 0)
							xRange = -xRange;

						if(yRange < 0)
							yRange = -yRange;

						int xRange2 = closestToTarget->GetX() - closest->GetTile()->GetX();
						int yRange2 = closestToTarget->GetY() - closest->GetTile()->GetY();

						if(xRange2 < 0)
							xRange2 = -xRange2;

						if(yRange2 < 0)
							yRange2 = -yRange2;

						if(xRange2+yRange2 > xRange+yRange)
						{
							closestToTarget = inRangeTiles[i];
							index = i;
						}

					}
				}

				if(bc->Move(closestToTarget))
				{
					moving = false;
					break;
				}
				else
				{
					inRangeTiles.erase(inRangeTiles.begin()+index);
				}

			}

		}
	}
	else
	{
		if(inRangeEnemies.size() <= 0)
			return false;
		else
		{
			GamePlayState * g = GamePlayState::GetInstance();
			vector<BaseCharacter*> * chs = g->GetCharacters();
			
			BaseCharacter * closest = nullptr;

			for(unsigned int i = 0; i < chs->size();i++)
			{
				if(closest == nullptr)
				{
					if((*chs)[i]->IsPlayer() != bc->IsPlayer())
						closest = (*chs)[i];
				}
				else
				{
					int xRange = (*chs)[i]->GetTile()->GetX() - bc->GetTile()->GetX();
					int yRange = (*chs)[i]->GetTile()->GetY() - bc->GetTile()->GetY();

					if(xRange < 0)
						xRange = -xRange;

					if(yRange < 0)
						yRange = -yRange;

					int xRange2 = closest->GetTile()->GetX() - bc->GetTile()->GetX();
					int yRange2 = closest->GetTile()->GetY() - bc->GetTile()->GetY();

					if(xRange2 < 0)
						xRange2 = -xRange2;

					if(yRange2 < 0)
						yRange2 = -yRange2;

					if(xRange2+yRange2 > xRange+yRange)
					{
						if((*chs)[i]->IsPlayer() != bc->IsPlayer())
							closest = (*chs)[i];
					}

				}
			}

			bool moving = true;
			//vector<int> tried;

			while(moving && inRangeTiles.size() > 0)
			{
				Tile * farthestToTarget = nullptr;
				int index;

				for(unsigned int i = 0; i < inRangeTiles.size();i++)
				{
					if(farthestToTarget == nullptr)
					{
						farthestToTarget = inRangeTiles[i];
						index = i;
					}
					else
					{
						int xRange = inRangeTiles[i]->GetX() - closest->GetTile()->GetX();
						int yRange = inRangeTiles[i]->GetY() - closest->GetTile()->GetY();

						if(xRange < 0)
							xRange = -xRange;

						if(yRange < 0)
							yRange = -yRange;

						int xRange2 = farthestToTarget->GetX() - closest->GetTile()->GetX();
						int yRange2 = farthestToTarget->GetY() - closest->GetTile()->GetY();

						if(xRange2 < 0)
							xRange2 = -xRange2;

						if(yRange2 < 0)
							yRange2 = -yRange2;

						if(xRange2+yRange2 < xRange+yRange)
						{
							farthestToTarget = inRangeTiles[i];
							index = i;
						}

					}
				}

				if(bc->Move(farthestToTarget))
				{
					moving = false;
					break;
				}
				else
				{
					inRangeTiles.erase(inRangeTiles.begin()+index);
				}

			}

		}
	}

	/*
	if((*AIManager::GetInstance()->GetAIChars())[this->characterIndex]->Move(TileManager::GetInstance()->GetTile((*AIManager::GetInstance()->GetAIChars())[this->characterIndex]->GetTile()->GetX()-1,(*AIManager::GetInstance()->GetAIChars())[this->characterIndex]->GetTile()->GetY())))
		return true;
	if((*AIManager::GetInstance()->GetAIChars())[this->characterIndex]->Move(TileManager::GetInstance()->GetTile((*AIManager::GetInstance()->GetAIChars())[this->characterIndex]->GetTile()->GetX(),(*AIManager::GetInstance()->GetAIChars())[this->characterIndex]->GetTile()->GetY()+1)))
		return true;
	if((*AIManager::GetInstance()->GetAIChars())[this->characterIndex]->Move(TileManager::GetInstance()->GetTile((*AIManager::GetInstance()->GetAIChars())[this->characterIndex]->GetTile()->GetX()+1,(*AIManager::GetInstance()->GetAIChars())[this->characterIndex]->GetTile()->GetY())))
		return true;
	if((*AIManager::GetInstance()->GetAIChars())[this->characterIndex]->Move(TileManager::GetInstance()->GetTile((*AIManager::GetInstance()->GetAIChars())[this->characterIndex]->GetTile()->GetX(),(*AIManager::GetInstance()->GetAIChars())[this->characterIndex]->GetTile()->GetY()-1)))
		return true;*/
	return false;
}

bool BaseAI::AIUseAction()
{
	// should not ever hit this breakpoint. should not ever be a base ai
	BaseCharacter * character = (*AIManager::GetInstance()->GetAIChars())[this->characterIndex];

	vector<BaseCharacter *> inRangeAllies;
	vector<BaseCharacter *> inRangeEnemies;

	TileManager * tm = TileManager::GetInstance();

	for(int x = 0; x < TileManager::GetInstance()->GetSizeX();x++)
	{
		for(int y = 0; y < TileManager::GetInstance()->GetSizeY();y++)
		{
			Tile * tile = tm->GetTile(x,y);

			if(tile->GetCharacter() == nullptr)
				continue;

			int xRange = tile->GetX() - character->GetTile()->GetX();
			int yRange = tile->GetY() - character->GetTile()->GetY();

			if(xRange < 0)
				xRange = -xRange;

			if(yRange < 0)
				yRange = -yRange;

			if(!(xRange + yRange > character->GetRng()))
			{
				if(tile->GetCharacter()->IsPlayer() == character->IsPlayer())
					inRangeAllies.push_back(tile->GetCharacter());
				else
				{
					inRangeEnemies.push_back(tile->GetCharacter());
				}
			}


		}
	}

	if(inRangeAllies.size() <= 0 && inRangeEnemies.size() <= 0)
		(*AIManager::GetInstance()->GetAIChars())[this->characterIndex]->Defend();		
	

	
	if(inRangeAllies.size() <= 0)
		(*AIManager::GetInstance()->GetAIChars())[this->characterIndex]->Defend();		
	else
		(*AIManager::GetInstance()->GetAIChars())[this->characterIndex]->Attack(inRangeEnemies[0]->GetTile());
	
	return true;
}
